package app.Insam.VNC;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

import java.util.List;
import java.util.ListIterator;

public class InsamAsyncWifiManager {
	static final String TAG = "InsamApp";	
	static final int SELF_TIMEOUT = 50*1000;	//50sec
	
	static final int MSG_DLGTEXT = 0x1;
	static final int MSG_FINISH = 0x2;	
	static final int FAULT_WIFION = 0x3;
	static final int FAULT_CONN = 0x4;
	
	int mAction;
	boolean mWifiOff;
	
	InsamMain mParent;	
	WifiManager mWifi;
	ProgressDialog mProgress;
	AlertDialog resultDlg;
	HandlerThread mWorker;
	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message _msg) {			
			Log.d(TAG, "main handler receive msg:"+_msg.what);			
			switch(_msg.what) {
			case MSG_DLGTEXT:
				//Log.d(TAG, "receive set text:"+_msg.obj);
				mProgress.setMessage((String)_msg.obj);	
				break;
			case MSG_FINISH:
				removeMessages(MSG_FINISH);		//remove self-finish msg 
				mProgress.dismiss();
				final int rtn = _msg.arg1;
				postDelayed(new Runnable() {	
					public void run() {
						onFinish(rtn);
					}
				}, 150);
				break;
			}
		}
	};	
	
	public InsamAsyncWifiManager(InsamMain _parent) {
		mParent = _parent;		
		mWifi = (WifiManager)mParent.getSystemService(Context.WIFI_SERVICE);
		
		resultDlg = new AlertDialog.Builder(mParent) 
		.setTitle(R.string.Conn_Failure)
		.setIcon(android.R.drawable.ic_dialog_alert) 
		.setPositiveButton(android.R.string.ok, null)
		.create();
	}
	
	public void connect(int _action) {
		mAction = _action;
		
		Message msg = new Message();
		msg.what = MSG_FINISH;
		msg.arg1 = FAULT_CONN;
		mHandler.sendMessageDelayed(msg, SELF_TIMEOUT);	//self finish(time out)
		
		mProgress = new ProgressDialog(mParent);
		mProgress.setTitle(R.string.Scan);	
		mProgress.setMessage(getString(R.string.text_Wait));
		mProgress.setCancelable(false);	
		mProgress.setButton(getString(android.R.string.cancel), new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface _dialog, int _whichButton) {
				sendFinishMessage(Activity.RESULT_CANCELED);
			}
		});	
		mProgress.show();
		
		mWorker = new HandlerThread("WorkerThread") {
			static final int MSG_SCANNING = 0x11;//17
			static final int MSG_CONNECTING = 0x12;
			static final int MSG_CONNECTING_CHECK = 0x13;
			static final int MSG_SELF_CHECK = 0x14;
			
			boolean connecting=false;
			int brCnt=0;
			
			List<ScanResult> mWifiScanList;			
			Handler mWorkerHandler = new Handler() {
				@Override
				public void handleMessage(Message _msg) {
					Log.d(TAG, "worker handler receive msg:"+_msg.what);
					
					switch(_msg.what) {
					case MSG_SCANNING:
						onOfficeScanning();
						break;
					case MSG_CONNECTING:
						connecting=true;
						sendSetTextMessage(R.string.text_Wifi_Conn);
						mWorkerHandler.sendEmptyMessageDelayed(MSG_CONNECTING_CHECK, 3000);	
						break;
					case MSG_CONNECTING_CHECK:	
						if(Check()) {	
							connecting=false;
						}						
						break;
					case MSG_SELF_CHECK:	
						if(brCnt==0) {
							Log.d(TAG, "self test check!!");
							Check();
						}
						brCnt=0;
						mWorkerHandler.sendEmptyMessageDelayed(MSG_SELF_CHECK, SELF_TIMEOUT/4);	
						break;
					}
				}
			};	
			
			BroadcastReceiver mReceiver = new BroadcastReceiver() {
				@Override
				public void onReceive(Context _context, Intent _intent) {
					if(connecting) return;
					
					if(_intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
						++brCnt;
						if(mWifi.getWifiState()==WifiManager.WIFI_STATE_ENABLED) {
							Log.v(TAG, "WIFI_STATE_ENABLED");
							mWifi.startScan();
							sendSetTextMessage(R.string.text_Wifi_Scan);
						}
						return;
					} 					
					if(_intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
						++brCnt;
						mWifiScanList = mWifi.getScanResults();
						if(mWifiScanList==null || mWifiScanList.size()==0) {
							Log.d(TAG, "No available AP");
							Check();
						} else {
							Log.d(TAG, "receive ssid list:"+mWifiScanList.size());
							if(mAction==InsamMain.EXTRA_HOME) {
								mWorkerHandler.sendEmptyMessageDelayed(MSG_CONNECTING, 10);	
							} else {
								mWorkerHandler.sendEmptyMessageDelayed(MSG_SCANNING, 10);		
							}
						}					
					} 
				}	
			};	

			@Override
			public void run() {
				mParent.registerReceiver(mReceiver, new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));	
				mParent.registerReceiver(mReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
				mWorkerHandler.sendEmptyMessageDelayed(MSG_SELF_CHECK, SELF_TIMEOUT/3);
				Check();
			}

			@Override
			public boolean quit() {
				mParent.unregisterReceiver(mReceiver);
				mWorkerHandler.removeMessages(MSG_SELF_CHECK);
				super.quit();
				return true;
			}	
			
			protected boolean Check() {	
				//Log.d(TAG, "Wifi Check");
				if(mWifi.isWifiEnabled()==false) {					
					if(on()==false) 
						sendFinishMessage(FAULT_WIFION);	
						return false;					
				} else {
					if(isConnected(mAction)) {
						sendFinishMessage(Activity.RESULT_OK);
						return false;
					}
					mWifi.startScan();
					sendSetTextMessage(R.string.text_Wifi_Scan);
				}
				return true;
			}
			
			protected void onOfficeScanning() {		
				ListIterator<ScanResult> result = mWifiScanList.listIterator();		
				
				String ssid=null;
				while(result.hasNext()) {
					ScanResult info = result.next();
					if(info.SSID.contains(InsamApp.OfficeSSID)) {
						Log.d(TAG, "detect office network!!");
						ssid = info.SSID;
						break;
					}				
				}
				if(ssid!=null) {					
					ListIterator<WifiConfiguration> cfgIt = mWifi.getConfiguredNetworks().listIterator();
					while(cfgIt.hasNext()) {
						WifiConfiguration cfg = cfgIt.next();
						if(cfg.SSID.contains(ssid)) {
							Log.d(TAG, "connecting office network!!");
							mWifi.enableNetwork(cfg.networkId, true);
							mWorkerHandler.sendEmptyMessageDelayed(MSG_CONNECTING, 10);	
							return;
						}							
					}
				}
				Check();
			}	
		};
		mWorker.setDaemon(true);
		mWorker.start();
	}	
	

	
	protected void onFinish(int _rtn) {
		Log.d(TAG, "onFinish:"+_rtn);
		
		mWorker.quit();	
		if(_rtn==Activity.RESULT_OK) {
			mParent.sendMessageConnect();
		} else {				
			if(_rtn!=Activity.RESULT_CANCELED) {
				showDialog(_rtn);
			}
			mParent.onFinishConnect();
		} 
	}
	
	protected void sendFinishMessage(int _state) {
		Message msg = new Message();
		msg.what = MSG_FINISH;
		msg.arg1 = _state;
		mHandler.sendMessageDelayed(msg, 10);	
	}
	

	protected void sendSetTextMessage(final int _r) {
		Message msg = new Message();
		msg.what = MSG_DLGTEXT;
		msg.obj = getString(_r);
		mHandler.sendMessageDelayed(msg, 10);	
	}
	
	private void showDialog(int _rtn) {
		String text;
		switch(_rtn) {
		case FAULT_WIFION:
			text = getString(R.string.text_Wifi_Failure);
			break;
		case FAULT_CONN:
			if(mAction==InsamMain.EXTRA_HOME) {
				text = getString(R.string.text_Conn_Failure);
			} else {
				text = getString(R.string.text_Office_Failure);
			}
			break;
		default:
			text = getString(R.string.text_Sorry);
		}
		resultDlg.setMessage(text);
		resultDlg.show();
	}
	
	protected boolean on() {		
		if(mWifi.setWifiEnabled(true)) {
			Log.v(TAG, "wifi on");
			sendSetTextMessage(R.string.text_Wifi_On);
			mWifiOff=true;
			return true;	
		}
		return false;
	}
	
	public void off() {
		if(mWifiOff) {
			Log.v(TAG, "wifi off");
			InsamWifiManager.mWifiOff=true;		//InsamWifiManager에서  wifi 꺼짐으로 인한 재검색을 막기 위함
			mWifi.setWifiEnabled(false);
			mWifiOff=false;
		}
	}
	
	public boolean isEnabled() {
		return mWifi.isWifiEnabled();
	}
	
	public boolean isConnected(int _actionId) {		
		WifiInfo info = mWifi.getConnectionInfo();
		
		if(info==null || info.getSSID()==null) {
			return false;
		} 
		
		if(_actionId == InsamMain.EXTRA_OFFICE && InsamApp.OfficeSSID!=null) {
			return info.getSSID().contains(InsamApp.OfficeSSID);
		} else {
			return true;
		}
	}
	
	public String getString(int _resId) {
		return mParent.getString(_resId);
	}

}